import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:path_provider/path_provider.dart';

/**
 * @Description: Path  内存路径管理工具类
 * @Author: 下雨了
 * @CreateDate: 2021-12-03 13:15
 * @UpdateUser: 更新者
 * @UpdateDate:  2021-12-03 13:15
 * @UpdateRemark: 更新说明
 * @Version: 1.0
 */
///
//
// dependencies:
//   path_provider: ^2.0.7
//

//定义一个top-level（全局）变量，页面引入该文件后可以直接使用 path
// final path = PathProviderUtils();

class PathProviderUtils {
  //私有构造函数
  PathProviderUtils._internal();

  //保存单例
  static final PathProviderUtils _pathUtils = PathProviderUtils._internal();

  //工厂构造函数
  factory PathProviderUtils() => _pathUtils;

  ///
  /// /data/user/0/com.xxxxx.xxxxx/cache
  ///
  /// On iOS, this uses the `NSCachesDirectory` API.
  ///
  /// On Android, this uses the `getCacheDir` API on the context.
  ///
  Future<String> getTempDir() async {
    Directory tempDir = await getTemporaryDirectory();
    String tempPath = tempDir.path;
    return tempPath;
  }



  ///
  /// /data/user/0/com.xxxxx.xxxxx/files
  ///
  /// On iOS, this uses the `NSApplicationSupportDirectory` API.
  /// If this directory does not exist, it is created automatically.
  ///
  /// On Android, this function uses the `getFilesDir` API on the context.
  ///
  Future<String> getAppSupPath() async {
    Directory appSupDir = await getApplicationSupportDirectory();
    String appSupPath = appSupDir.path;
    return appSupPath;
  }



  ///
  /// /data/user/0/com.xxxxx.xxxxx/app_flutter
  ///
  /// On iOS, this uses the `NSDocumentDirectory` API. Consider using
  /// [getApplicationSupportDirectory] instead if the data is not user-generated.
  ///
  /// On Android, this uses the `getDataDirectory` API on the context. Consider
  /// using [getExternalStorageDirectory] instead if data is intended to be visible
  /// to the user.
  ///
  Future<String> getAppDocPath() async {
    Directory appDocDir = await getApplicationDocumentsDirectory();
    String appDocPath = appDocDir.path;
    return appDocPath;
  }



  ///
  /// /storage/emulated/0/Android/data/com.xxxxx.xxxxx/files
  ///
  /// On iOS, this function throws an [UnsupportedError] as it is not possible
  /// to access outside the app's sandbox.
  ///
  /// On Android this uses the `getExternalFilesDir(null)`.
  Future<String> getExtPath() async {
    Directory? extStoDir = await getExternalStorageDirectory();
    String? extStoPath = extStoDir?.path;
    if (extStoPath == null) {
      return "";
    }
    return extStoPath;
  }

  /// 判断文件夹是否存在，不存在则创建，存在不处理
  Future<String> isExists(String newPath) async {
    Directory directory = new Directory(newPath);
    try {
      bool exists = await directory.exists();
      if (!exists) {
        // 创建所有不存在的目录
        await directory.create(recursive: true);
        debugPrint("创建成功");
      } else {
        debugPrint("已存在");
      }
    } catch (e) {
      print(e);
    }
    return directory.path.toString();
  }

  /// 删除指定的文件
  Future<bool> deleteFile(String path) async {
    File file = new File(path);
    bool exists = await file.exists();
    try {
      if (exists) {
        file.deleteSync();
        debugPrint("删除文件成功");
        return true;
      }
    } catch (e) {
      debugPrint("删除文件出错了: $e");
    }
    return false;
  }

  //================================================================================================================

  /// 获取缓存目录
  Future<Directory> getCacheDir() async {
    Directory directory = await getTemporaryDirectory();
    return directory;
  }

  /// 加载缓存 返回目录大小
  Future<String> loadCache() async {
    // print("加载缓存");
    Directory directory = await getCacheDir();
    // directory.list(followLinks: false, recursive: true).listen((file) {
    //   print(file.path);
    // });
    double value = await _getTotalSizeOfFilesInDir(directory);
    // print('临时目录大小: ' + value.toString());
    return _renderSize(value);
  }

  /// 清除缓存
  Future<void> clearAllCache() async{
    Directory directory = await getCacheDir();
    await delDir(directory);
  }


  /// 循环计算文件的大小（递归）
  Future<double> _getTotalSizeOfFilesInDir(FileSystemEntity file) async {
    if (file is File) {
      int length = await file.length();
      return double.parse(length.toString());
    }
    if (file is Directory) {
      final List<FileSystemEntity> children = file.listSync();
      double total = 0;
      if (children != null) {
        for (final FileSystemEntity child in children) {
          total += await _getTotalSizeOfFilesInDir(child);
        }
        return total;
      }
    }
    return 0;
  }

  /// 格式化缓存文件大小
  String _renderSize(double value) {
    if (value == null) {
      return "0";
    }
    List<String> unitArr = []
      ..add("B")
      ..add("K")
      ..add("M")
      ..add("G");
    int index = 0;
    while (value > 1024) {
      index++;
      value = value / 1024;
    }
    String size = value.toStringAsFixed(2);
    return size + unitArr[index];
  }

  ///递归方式删除目录
  Future<void> delDir(FileSystemEntity file) async {
    try {
      if (file is Directory) {
        final List<FileSystemEntity> children = file.listSync();
        for (final FileSystemEntity child in children) {
          await delDir(child);
        }
      }
      await file.delete();
    } catch (e) {
      print(e);
    }
  }
}
